/**
 * Copyright (C) 2010 altuure <altuure [AT] gmail [DOT] com> http://www.altuure.com/projects/yagdao
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.altuure.yagdao.jpa;

import com.altuure.yagdao.YLimit;
import com.altuure.yagdao.base.DAOTestHelper;
import com.altuure.yagdao.dao.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.persistence.*;
import java.util.List;
import java.util.Map;

public class JpaDAOTestHelper extends DAOTestHelper {
    public static final Log log = LogFactory.getLog(JpaDAOTestHelper.class);

    protected EntityManagerFactory entityManagerFactory;

    protected EntityTransaction tx;

    private DefaultEntityManagerAccessor accessor;
    private static JpaDAOTestHelper instance = null;

    private JpaDAOTestHelper() {
        super();

    }

    public EntityManager getEntityManager() {
        return accessor.getEntityManager();
    }

    public static synchronized JpaDAOTestHelper getInstance() {
        if (instance == null) {
            instance = new JpaDAOTestHelper();
            try {
                instance.init();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return instance;
    }

    @Override
    protected void initDAO() throws Exception {

        orderDAO = (OrderDAO) GenericJpaDAOFactory.createInstance(OrderDAO.class, accessor);
        orderItemDAO = (OrderItemDAO) GenericJpaDAOFactory.createInstance(OrderItemDAO.class, accessor);
        productDAO = (ProductDAO) GenericJpaDAOFactory.createInstance(ProductDAO.class, accessor);
        simpleBeanDAO = (SimpleBeanDAO) GenericJpaDAOFactory.createInstance(SimpleBeanDAO.class, accessor);
        simpleBeanNewDAO = (SimpleBeanNewDAO) GenericJpaDAOFactory.createInstance(SimpleBeanNewDAO.class, accessor);
        simpleBeanAppendDAO = (SimpleBeanAppendDAO) GenericJpaDAOFactory.createInstance(SimpleBeanAppendDAO.class, accessor);
    }

    @Override
    protected void initDB() throws Exception {
        if (entityManagerFactory != null)
            return;
        entityManagerFactory = Persistence.createEntityManagerFactory("hibernate_unit", new java.util.HashMap());
        accessor = new DefaultEntityManagerAccessor(entityManagerFactory);

    }

    @Override
    protected void beginTx() {
        tx = getEntityManager().getTransaction();
        tx.begin();
        getEntityManager().clear();

    }

    @Override
    protected void commitTx() {
        tx.commit();
        accessor.clear();

    }

    @Override
    protected void rollbackTx() {
        tx.rollback();
        accessor.clear();

    }

    @Override
    public void save(Object object) {
        accessor.getEntityManager().persist(object);

    }

    @Override
    public Object executePageQuery(String queryString, YLimit page, Object... args) {
        Query query = getEntityManager().createQuery(queryString);
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                Object object = args[i];
                query.setParameter(i + 1, object);
            }
        }
        if (page != null && page.getFirstResult() > 0)
            query.setFirstResult(page.getFirstResult());
        if (page != null && page.getPageSize() > 0)
            query.setMaxResults(page.getPageSize());
        List list = query.getResultList();
        if (list.isEmpty())
            log.warn(" queryReturns empty:" + queryString);

        return list;
    }

    @Override
    public Object executePageQuery(String queryString, YLimit page, Map<String, Object> args) {
        Query query = getEntityManager().createQuery(queryString);
        for (String key : args.keySet()) {

            query.setParameter(key, args.get(key));
        }
        if (page != null && page.getFirstResult() > 0)
            query.setFirstResult(page.getFirstResult());
        if (page != null && page.getPageSize() > 0)
            query.setMaxResults(page.getPageSize());
        List list = query.getResultList();
        if (list.isEmpty())
            log.warn(" queryReturns empty:" + queryString);

        return list;
    }

    public Object executeSingleQuery(String queryString, Object... args) {
        Query query = getEntityManager().createQuery(queryString);
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                Object object = args[i];
                query.setParameter(i + 1, object);
            }
        }

        return query.getSingleResult();
    }

    public Object executeSingleQuery(String queryString, Map<String, Object> args) {
        Query query = getEntityManager().createQuery(queryString);
        for (String key : args.keySet()) {

            query.setParameter(key, args.get(key));
        }

        return query.getSingleResult();
    }

    /**
     * @param args arguments
     */
    public static void main(String[] args) {
        new JpaDAOTestHelper();

    }

    @Override
    public Object get(Class clz, Long id) {
        return getEntityManager().find(clz, id);
    }

    @Override
    public Object executeNamedQuery(String queryString, YLimit page, Map<String, Object> args) {
        Query query = getEntityManager().createNamedQuery(queryString);
        for (String key : args.keySet()) {

            query.setParameter(key, args.get(key));
        }
        if (page != null && page.getFirstResult() > 0)
            query.setFirstResult(page.getFirstResult());
        if (page != null && page.getPageSize() > 0)
            query.setMaxResults(page.getPageSize());
        List list = query.getResultList();
        if (list.isEmpty())
            log.warn(" queryReturns empty:" + queryString);

        return list;
    }

    @Override
    public Object executeNamedQuery(String queryString, YLimit page, Object... args) {
        Query query = getEntityManager().createNamedQuery(queryString);
        for (int i = 0; i < args.length; i++) {
            Object object = args[i];
            query.setParameter(i + 1, object);
        }
        if (page != null && page.getFirstResult() > 0)
            query.setFirstResult(page.getFirstResult());
        if (page != null && page.getPageSize() > 0)
            query.setMaxResults(page.getPageSize());
        List list = query.getResultList();
        if (list.isEmpty())
            log.warn(" queryReturns empty:" + queryString);

        return list;
    }

}
